package com.koron.common.web.electronicsignature.service;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.system.OsInfo;
import cn.hutool.system.SystemUtil;
import com.alibaba.fastjson.JSONObject;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.domain.proto.storage.DownloadCallback;
import com.github.tobato.fastdfs.service.DefaultFastFileStorageClient;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfWriter;
import com.koron.bean.base.Attachment;
import com.koron.bean.base.Response;
import com.koron.bean.system.staff.vo.EamUser;
import com.koron.common.core.business.common.service.AttachmentService;
import com.koron.common.core.business.configsettings.utils.ConfigInfoTool;
import com.koron.common.core.business.workflow.util.TextUtil;
import com.koron.common.core.config.ThreadLocalContext;
import com.koron.common.core.util.StringUtils;
import com.koron.common.web.electronicsignature.bean.ElectronicSignature;
import com.koron.common.web.electronicsignature.bean.ElectronicSignatureQuery;
import com.koron.common.web.electronicsignature.fegin.ElectronicSignatureExperimentService;
import com.koron.common.web.electronicsignature.fegin.ElectronicSignatureTicketService;
import com.koron.common.web.electronicsignature.mapper.ElectronicSignatureMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.koron.ebs.mybatis.SessionFactory;
import org.koron.ebs.mybatis.TaskAnnotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Slf4j
@Service
public class ElectronicSignatureService {

    private EamUser getCurrUser() {
        return ThreadLocalContext.get();
    }

    @Autowired
    private ElectronicSignatureTicketService electronicSignatureTicketService;

    @Autowired
    private ElectronicSignatureExperimentService experimentService;

    @Autowired
    private AttachmentService attachmentService;

    @Autowired
    private DefaultFastFileStorageClient storageClient;

    @TaskAnnotation("createByFile")
    public Response createByFile(SessionFactory factory, String url, MultipartFile file, Map<String, String> formData, Map<String, String> headerParams, String workTicketId, String fileId) {
        ElectronicSignatureMapper electronicSignatureMapper = factory.getMapper(ElectronicSignatureMapper.class);
        CloseableHttpClient httpClient = HttpClients.createDefault();
        String result = "";

        try {
            // 1. 请求连接
            HttpPost httpPost = new HttpPost(url);
            // 2. 设置请求头
            if (headerParams != null && headerParams.size() > 0) {
                for (Map.Entry<String, String> pair : headerParams.entrySet()) {
                    String value = pair.getValue();
                    String key = pair.getKey();
                    if (StringUtils.isNotEmpty(value)) {
                        httpPost.setHeader(key, value);
                    }
                }
            }
            // 3. 设置编码格式，解决返回中文乱码问题
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            builder.setCharset(Charset.forName("utf-8"));
            builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
            // 4. 文件传输http请求头(multipart/form-data)
            if (Objects.isNull(file)) {
                if (StringUtils.isNotEmpty(fileId)) {
                    Attachment attachment = attachmentService.getById(fileId);
                    if (Objects.isNull(attachment) || org.apache.commons.lang3.StringUtils.isAnyBlank(attachment.getPath(),attachment.getName(),attachment.getExtension())) {
                        return Response.fail("附件信息不能为空");
                    }
                    StorePath storePath = StorePath.parseFromUrl(attachment.getPath());
                    storageClient.downloadFile(storePath.getGroup(), storePath.getPath(), (DownloadCallback<ResponseEntity>) inputStream -> {
                        byte[] buffer = new byte[10240];
                        BufferedInputStream bis = new BufferedInputStream(inputStream);
                        builder.addBinaryBody("file", bis, ContentType.MULTIPART_FORM_DATA, attachment.getName());// 文件流
                        return null;
                    });
                }
                //前端文件为空 附件id为空
                File defaultfile = getDefaultfilePdfFile();//获取默认空pdf文件路径
                formData.put("fileType","pdf");
                if (!FileUtil.exist(defaultfile)) {
                    Document document = new Document();
                    PdfWriter.getInstance(document, new FileOutputStream(defaultfile));//不存在则创建
                    document.open();
                    document.add(new Paragraph(" "));//这地方必须要有内容
                    document.close();
                }
                InputStream inputstream = new FileInputStream(defaultfile);
                builder.addBinaryBody("file", inputstream, ContentType.MULTIPART_FORM_DATA, defaultfile.getName());// 文件流
            } else {
                String fileName = file.getOriginalFilename();
                builder.addBinaryBody("file", file.getInputStream(), ContentType.MULTIPART_FORM_DATA, fileName);// 文件流
            }



            // 5. 字节传输http请求头(application/json)
            ContentType contentType = ContentType.create("application/json", Charset.forName("UTF-8"));
            if (formData != null && formData.size() > 0) {
                for (Map.Entry<String, String> e : formData.entrySet()) {
                    String value = e.getValue();
                    if (StringUtils.isNotEmpty(value)) {
                        builder.addTextBody(e.getKey(), value, contentType);// 类似浏览器表单提交，对应input的name和value
                    }
                }
            }
            // 6. 获取响应结果
            HttpEntity entity = builder.build();
            httpPost.setEntity(entity);
            HttpResponse response = httpClient.execute(httpPost);// 执行提交
            HttpEntity responseEntity = response.getEntity();
            if (responseEntity != null) {
                // 将响应内容转换为字符串
                result = EntityUtils.toString(responseEntity, Charset.forName("UTF-8"));
            }
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        } catch (DocumentException e){
            log.error("pdf生成异常");
            log.error(e.getMessage(), e);
        }
        IoUtil.close(httpClient);
        // 7. 数据库保存该条数据（继承自BaseBean的数据都有自动填充）
        Map<String, String> map = TextUtil.toMapFromString(result);
        String documentId = map.get("documentId");
        if (StringUtils.isNotEmpty(documentId)) {
            ElectronicSignature electronicSignature = new ElectronicSignature();
            electronicSignature.setWorkTicketId(workTicketId);
            electronicSignature.setDocumentId(map.get("documentId"));
            electronicSignatureMapper.insert(electronicSignature);
        } else {
            return Response.fail("未返回documentId");
        }

        result = documentId;
        return Response.success(result);
    }

    /**
     * 获取默认空pdf文件路径
     * @return
     */
    private File getDefaultfilePdfFile() {
        String path = "";
        String fileName = "默认空签名.pdf";
        Map<String, String> map = ConfigInfoTool.getConfigByCode("common", "storage");

        OsInfo osInfo = SystemUtil.getOsInfo();
        if (osInfo.isWindows()) {
            path = map.get("winLocation");
        }
        if (osInfo.isLinux()) {
            path = map.get("linuxLocation");
        }
        return new File(path + fileName);
    }

    @TaskAnnotation("createByCategory")
    public Response createByCategory(SessionFactory factory, String url, Map<String, String> formData,
                                     Map<String, String> headerParams, String workTicketId, String documentId) {
        ElectronicSignatureMapper electronicSignatureMapper = factory.getMapper(ElectronicSignatureMapper.class);
        CloseableHttpClient httpClient = HttpClients.createDefault();
        String result = "";

        try {
            // 1. 请求连接
            HttpPost httpPost = new HttpPost(url);
            // 2. 设置请求头
            if (headerParams != null && headerParams.size() > 0) {
                for (Map.Entry<String, String> pair : headerParams.entrySet()) {
                    String value = pair.getValue();
                    String key = pair.getKey();
                    if (StringUtils.isNotEmpty(value)) {
                        httpPost.setHeader(key, value);
                    }
                }
            }
            String data = JSONObject.toJSONString(formData);
            log.info("电子签章创建合同json:{}", data);
            StringEntity s = new StringEntity(data, "UTF-8");
            s.setContentEncoding("UTF-8");
            s.setContentType("application/json");//发送json数据需要设置contentType
            httpPost.setEntity(s);
            HttpResponse response = httpClient.execute(httpPost);// 执行提交
            HttpEntity responseEntity = response.getEntity();
            if (responseEntity != null) {
                // 将响应内容转换为字符串
                result = EntityUtils.toString(responseEntity, Charset.forName("UTF-8"));
            }
        } catch (ClientProtocolException e) {
            log.error(e.getMessage(), e);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        // 7. 数据库保存该条数据（继承自BaseBean的数据都有自动填充）
        Map<String, String> map = TextUtil.toMapFromString(result);
        String contractId = map.get("contractId");
        if (StringUtils.isNotEmpty(contractId)) {
            ElectronicSignatureQuery electronicSignatureQuery = new ElectronicSignatureQuery();
            electronicSignatureQuery.setWorkTicketId(workTicketId);
            electronicSignatureQuery.setDocumentId(documentId);
            ElectronicSignature electronicSignature = electronicSignatureMapper.getSingle(electronicSignatureQuery);
            electronicSignature.setContractId(contractId);
            electronicSignatureMapper.update(electronicSignature);
        } else {
            return Response.fail("未返回合同id");
        }

        result = contractId;
        return Response.success(result);
    }

    @TaskAnnotation("getSingle")
    public ElectronicSignature getSingle(SessionFactory factory, ElectronicSignatureQuery electronicSignatureQuery) {

        ElectronicSignatureMapper electronicSignatureMapper = factory.getMapper(ElectronicSignatureMapper.class);
        ElectronicSignature single = electronicSignatureMapper.getSingle(electronicSignatureQuery);

        return single;

    }

    @TaskAnnotation("callback")
    public Response callback(SessionFactory factory, String contractId, String tenantName, String status) {
        ElectronicSignatureMapper electronicSignatureMapper = factory.getMapper(ElectronicSignatureMapper.class);

        ElectronicSignatureQuery electronicSignatureQuery = new ElectronicSignatureQuery();
        electronicSignatureQuery.setContractId(contractId);
        ElectronicSignature electronicSignature = electronicSignatureMapper.getSingle(electronicSignatureQuery);
        String workTicketId = electronicSignature.getWorkTicketId();

        Response response = electronicSignatureTicketService.electronicSignatureCallback(workTicketId, tenantName, status);
        Object data = response.getData();
        if (data == null) {
            return Response.fail("具体业务回调失败");
        } else if (data.toString().contains("回调成功")) {
            return Response.success("工作票回调成功");
        } else {
            return Response.fail("回调失败,原因不明");
        }
    }

    @TaskAnnotation("callbackExperiment")
    public Response callbackExperiment(SessionFactory factory, String contractId, String tenantName, String contact, String type, String status) {

        List<ElectronicSignature> electronicSignatureList = queryByContractId(factory, contractId);

        Assert.notEmpty(electronicSignatureList, "找不到对应的业务信息");

        String workTicketId = electronicSignatureList.get(0).getWorkTicketId();

        String documentId = electronicSignatureList.get(0).getDocumentId();

        Response response = experimentService.electronicSignatureCallback(workTicketId, documentId, tenantName, contact, type, status);

        Object data = response.getData();
        if (data == null) {
            return Response.fail("试验工单回调失败");
        } else if (data.toString().equals("试验工单回调成功")) {
            return Response.success("试验工单回调成功");
        } else {
            return Response.fail("回调失败,原因不明");
        }
    }

    @TaskAnnotation("queryByContractId")
    public List<ElectronicSignature> queryByContractId(SessionFactory factory, String contractId) {
        ElectronicSignatureMapper electronicSignatureMapper = factory.getMapper(ElectronicSignatureMapper.class);
        ElectronicSignatureQuery electronicSignatureQuery = new ElectronicSignatureQuery();
        electronicSignatureQuery.setContractId(contractId);
        List<ElectronicSignature> electronicSignatureList = electronicSignatureMapper.queryByContractId(electronicSignatureQuery);
        return electronicSignatureList;
    }

}
